use crate::model;
use crate::request::{UpdateTaskRequest, CreateTaskRequest};

use http::StatusCode;
use log::error;

use anyhow::anyhow;
use poem::http;
use rbatis::PageRequest;
use validator::Validate;

pub struct TaskListBiz;

impl TaskListBiz {
    pub async fn detail(
        rb: &rbatis::RBatis,
        id: &i64,
    ) -> anyhow::Result<model::TaskList> {
        model::TaskList::select_by_id(rb, id)
            .await
            .map_err(|err| {
                error!("db ops error => {err}");
                anyhow!(StatusCode::INTERNAL_SERVER_ERROR.canonical_reason().unwrap())
            })?
            .ok_or(anyhow!(StatusCode::NOT_FOUND.canonical_reason().unwrap()))
    }
    
    pub async fn delete(
        rb: &rbatis::RBatis,
        id: &i64,
    ) -> anyhow::Result<()> {
        let result = model::TaskList::delete_by_column(rb, "id", id)
            .await
            .map_err(|err| {
                error!("db delete error => {err}");
                anyhow!(StatusCode::INTERNAL_SERVER_ERROR.canonical_reason().unwrap())
            })?;
        
        if result.rows_affected == 0 {
            return Err(anyhow!(StatusCode::NOT_FOUND.canonical_reason().unwrap()));
        }
        Ok(())
    }
    
    pub async fn create(
        rb: &rbatis::RBatis,
        req: CreateTaskRequest,
    ) -> anyhow::Result<model::TaskList> {
        req.validate().map_err(|err| anyhow!(err))?;
        let now = chrono::Local::now().timestamp_millis();
        let CreateTaskRequest { title, description, done } = req;
        let task = model::TaskList {
            id: None,
            title,
            description,
            done,
            created_at: Some(now),
            updated_at: Some(now),
        };

        model::TaskList::insert(rb, &task)
            .await
            .map_err(|err| {
                error!("db create error => {err}");
                anyhow!(StatusCode::INTERNAL_SERVER_ERROR.canonical_reason().unwrap())
            })?;
        
        Ok(task)
    }
    
    pub async fn update(
        rb: &rbatis::RBatis,
        req: UpdateTaskRequest,
    ) -> anyhow::Result<()> {
        req.validate().map_err(|err| anyhow!(err))?;
        let UpdateTaskRequest { id, title, description, done } = req;
        // 先查询现有数据
        let mut existing = model::TaskList::select_by_id(rb, &id)
            .await?
            .ok_or(anyhow!(StatusCode::NOT_FOUND.canonical_reason().unwrap()))?;

        // 更新字段
        existing.title = title;
        existing.description = description;
        existing.done = done;
        existing.updated_at = Some(chrono::Local::now().timestamp_millis());

        // 执行更新
        let affected_rows = model::TaskList::update_by_column(rb, &existing, "id")
            .await
            .map_err(|err| {
                error!("db update error => {err}");
                anyhow!(StatusCode::INTERNAL_SERVER_ERROR.canonical_reason().unwrap())
            })?
            .rows_affected;

        if affected_rows == 0 {
            return Err(anyhow!(StatusCode::NOT_FOUND.canonical_reason().unwrap()));
        }
        Ok(())
    }

    pub async fn list(
        rb: &rbatis::RBatis,
        page: Option<u64>,
        page_size: Option<u64>,
        title: Option<String>,
    ) -> anyhow::Result<Vec<model::TaskList>> {
        let page = page.unwrap_or(1);
        let page_size = page_size.unwrap_or(10);
        let title = title.unwrap_or("".to_string());
        let result = model::TaskList::select_page_by_title(rb, &PageRequest::new(page, page_size), &title)
            .await
            .map_err(|err| {
                error!("db list by title error => {err}");
                anyhow!(StatusCode::INTERNAL_SERVER_ERROR.canonical_reason().unwrap())
            })?;

        Ok(result.records)
    }
}